/**
  ******************************************************************************
  * @file    common_include.c
  * @author  ashuai0110
  * @version V2.4
  * @date    2024-09-24
  * @brief   公共引用文件(所有组件都需包含此文件)
  *
  ******************************************************************************
  * @attention
  *
  * 版权声明:内容为编者(ashuai0110)原创,使用请注明出处,当然,你也可以不这样做^_^
  * 出处链接:https://gitee.com/ashuai0110/mcu_reuse_development_module.git
  *
  * Change Logs:
  * Date          Author        Notes
  * 2023-10-17    ashuai0110    完成基本内容
  * 2023-12-28    ashuai0110    新增组件计时节拍接口
  * 2024-01-04    ashuai0110    修改组件计时节拍初值为1
  * 2024-03-26    ashuai0110    增加组件时间戳相关接口
  * 2024-07-01    ashuai0110    增加常用函数指针类型重定义
  * 2024-07-24    ashuai0110    增加组件延时函数和部分宏定义
  * 2024-08-16    ashuai0110    增加中断控制开关宏,修改中断控制宏内容
  * 2024-08-26    ashuai0110    修改断言处理,将部分宏移至module_config.h
  * 2024-09-05    ashuai0110    增加编译提示
  *
  ******************************************************************************
  */

/* 包含头文件-----------------------------------------------------------------*/
#include "common_include.h"

/**
 * @addtogroup common
 * @{
 */

/**
 * @defgroup common_include common_include
 * @{
 */

/* 私有宏定义-----------------------------------------------------------------*/

/* 私有类型定义---------------------------------------------------------------*/

/* 私有变量-------------------------------------------------------------------*/
/**
 * @defgroup common_include_local_variables common include local variables
 * @{
 */

static volatile uint32_t mwTicks = 1; /*!< 组件计时节拍 */

#if _MW_TIME_STAMP
static const char monthTable[12][3] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", \
                                       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; /*!< 月简称对照表 */
static const char weekTable[7][3] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; /*!< 周简称对照表 */
static volatile uint32_t mwTimeStamp; /*!< 组件时间戳 */
#endif

/**
 * @}
 */

/* 全局变量-------------------------------------------------------------------*/

/* 私有函数原型---------------------------------------------------------------*/
/**
 * @defgroup common_include_local_functions common include local functions
 * @{
 */

#if _MW_TIME_STAMP
/**
  * @brief  以指定分割符分割字符串
  *
  * @note   pSrc = "cmd 1 2 3", 空格分割
  *         pBuf[0] = "cmd"
  *         pBuf[1] = "1"
  *         pBuf[2] = "2"
  *         pBuf[3] = "3"
  *
  * @param  pBuf : 分解后存放的缓存区
  *
  * @param  pSrc : 源数据
  *
  * @param  flg  : 单字节分割符
  *
  * @param  num  : 期望分割数量
  *
  * @retval 返回实际分割数量
  */
static uint16_t module_split(char *pBuf[], char *pSrc, char flg, uint16_t num)
{
    uint16_t cnt = 0;
    
    MW_ASSERT_PARAM(IS_VALID_POINTER(pBuf));
    MW_ASSERT_PARAM(IS_VALID_POINTER(pSrc));
    
    /* 缓存区先存放第一个字符串首地址 */
    pBuf[cnt++] = pSrc;
    while(1)
    {
        /* 若当前字符与参数flg相同 */
        if(*pSrc == flg)
        {
            *pSrc = '\0'; /* 当前字符改为'\0' 代表字符串到此结束 */
            /* 若分割数量达到参数num则break */
            if(cnt >= num)
            {
                break;
            }
            pBuf[cnt++] = pSrc + 1; /* 缓存区存放下一个字符串首地址 */
        } /* 若当前字符与结束符1或结束符2或'\0'相同则break */
        else if('\r' == *pSrc || '\n' == *pSrc|| '\0' == *pSrc)
        {
            *pSrc = '\0';
            break;
        }
        pSrc++; /* 当前字符地址自增 */
    }
    
    return cnt;
}
#endif

/**
 * @}
 */

/**
 * @defgroup common_include_global_functions common include global functions
 * @{
 */

/**
  * @brief  组件计时节拍累计
  *
  * @note   此接口全组件共用需用户对接底层systick或timer等,若使用的组件无需时基则无需对接
  *
  * @param  ticks : 累计时间ms(如轮询周期是10ms则填10,是1ms则填1)
  *
  * @retval None
  */
void mw_tick_inc(uint32_t ticks)
{
    mwTicks += ticks;
}

/**
  * @brief  获取组件计时节拍
  *
  * @param  None
  *
  * @retval 返回当前节拍数ms
  */
uint32_t mw_tick_get(void)
{
    return mwTicks;
}

/**
  * @brief  组件毫秒延时
  *
  * @note   若使用组件提供的延时功能,参数应小于0x7FFFFFFF,否则用户需自行重定义
  *
  * @param  ms : 毫秒延时时间
  *
  * @retval None
  */
__weak void mw_delay_ms(uint32_t ms)
{
    uint32_t curTicks = mw_tick_get();

    while((mw_tick_get() - curTicks) <= ms);
}

/**
  * @brief  组件微秒延时
  *
  * @note   不提供此函数功能,仅提供接口函数,若某些组件需要使用此接口,用户需自行重定义
  *
  * @param  us : 微秒延时时间
  *
  * @retval None
  */
__weak void mw_delay_us(uint32_t us)
{
    MW_UNUSED(us);

    MW_ERROR_LOG("the user must define this function!");
}

#if _MW_ASSERT_PARAM
/**
  * @brief  参数断言失败
  *
  * @note   组件仅提供断言失败提示,若需要实现其他功能,用户需自行重定义
  *
  * @param  file : 文件路径
  *
  * @param  line : 所在行号
  *
  * @retval None
  */
__weak void mw_assert_failed(uint8_t *file, uint32_t line)
{
    MW_PRINT_FUNC("[%s:%d]ERROR: wrong parameters value!\r\n", file, line);
    MW_DISABLE_GLOBAL_INT();
    while(1);
}
#endif

#if _MW_TIME_STAMP
/**
  * @brief  组件时间戳初始化
  *
  * @param  baseTime : 时间戳
  *
  * @retval None
  */
void mw_time_stamp_init(uint32_t baseTime)
{
    mwTimeStamp = baseTime;
}

/**
  * @brief  组件时间戳1s计时累计
  *
  * @note   此接口需用户对接底层systick或timer等
  *
  * @param  None
  *
  * @retval None
  */
void mw_time_stamp_1s(void)
{
    mwTimeStamp += 1;
}

/**
  * @brief  获取组件时间戳
  *
  * @param  None
  *
  * @retval 返回当前时间戳
  */
uint32_t mw_time_stamp_get(void)
{
    return mwTimeStamp;
}

/**
  * @brief  由组件时间结构体转换为时间戳
  *
  * @param  mwTime : 组件时间结构体
  *
  * @retval 返回时间戳
  */
uint32_t mw_time_stamp_conv(mw_time_t mwTime)
{
    uint32_t timeTmp;
    struct tm tmTmp;
    
    tmTmp.tm_year = mwTime.year - 1900;
    tmTmp.tm_mon = mwTime.month - 1;
    tmTmp.tm_mday = mwTime.day;
    tmTmp.tm_hour = mwTime.hour;
    tmTmp.tm_min = mwTime.minute;
    tmTmp.tm_sec = mwTime.second;
    timeTmp = mktime(&tmTmp);
    
    return timeTmp;
}

/**
  * @brief  由时间戳转换为组件时间结构体
  *
  * @param  _time     : 组件时间结构体指针
  *
  * @param  timeStamp : 时间戳
  *
  * @retval None
  */
void mw_time_std_conv(mw_time_t *_time, uint32_t timeStamp)
{
    time_t timeTmp = (time_t)timeStamp;
    struct tm tmTmp;
    
    tmTmp = *localtime(&timeTmp);
    _time->year = tmTmp.tm_year + 1900;
    _time->month = tmTmp.tm_mon + 1;
    _time->day = tmTmp.tm_mday;
    _time->week = tmTmp.tm_wday == 0 ? 7 : tmTmp.tm_wday;
    _time->hour = tmTmp.tm_hour;
    _time->minute = tmTmp.tm_min;
    _time->second = tmTmp.tm_sec;
}

/**
  * @brief  由sntp时间字符串格式转换为组件时间结构体
  *
  * @param  _time    : 组件时间结构体指针
  *
  * @param  sntpTime : sntp时间字符串
  *
  * @retval None
  */
void mw_time_sntp_conv(mw_time_t *_time, char *sntpTime)
{
    char *buf[5];
    uint8_t index;
    
    sntpTime = strstr(sntpTime, ":") + sizeof(char);
    if(5 == module_split(buf, sntpTime, ' ', 5))
    {
        index = 0;
        do {
            if(0 == strncmp(buf[0], weekTable[index++], strlen(buf[0]))) { break; }
        } while(index < 7);
        _time->week = index;
        index = 0;
        do {
            if(0 == strncmp(buf[1], monthTable[index++], strlen(buf[1]))) { break; }
        } while(index < 12);
        _time->month = index;
        _time->day = atoi(buf[2]);
        _time->year = atoi(buf[4]);
        if(3 == module_split(buf, buf[3], ':', 3))
        {
            _time->hour = atoi(buf[0]);
            _time->minute = atoi(buf[1]);
            _time->second = atoi(buf[2]);
        }
    }
}
#endif

/**
 * @}
 */

/**
 * @}
 */

/**
 * @}
 */
